I had the same problem even with "Audio, AirPlay and Picture in Picture" background mode enabled and with all the AVAudioSession.setActive(true) and AVAudioSession.setCategory(...) calls.
We run some tests and it seems Apple made things more restrictive since iOS 18 (it was working on iOS 17.6). The only fix I found is to use the good old MPVolumeView as a substitute, but there's a catch - it's mandatory to add it to UI otherwise it will always return volume of 0.
In SwiftUI it was as simple as creating a UI component:
import MediaPlayer
import SwiftUI
struct VolumeSlider: UIViewRepresentable {
private let volumeView: MPVolumeView = MPVolumeView()
func makeUIView(context: Context) -> MPVolumeView {
return volumeView
}
func updateUIView(_ view: MPVolumeView, context: Context) {}
func getVolume() -> Float {
if let slider = volumeView.subviews.first(where: { $0 is UISlider }) as? UISlider {
return slider.value
}
return AVAudioSession.sharedInstance().outputVolume
}
}
And then in your SwiftUI view you can add it like:
struct YourView: View {
private let volumeControl: VolumeSlider = VolumeSlider()
@ViewBuilder
var body: some View {
//... your controls here ...
// This is a hack to make volume control work, but be invisible
volumeControl.frame(height: .zero).clipped()
Spacer(minLength: .zero)
}
private func someMethodThatRelatesToVolumeControl() {
let volume = volumeControl.getVolume()
// use the actual volume value
}
}
Topic:
Media Technologies
SubTopic:
Audio
Tags: